#ifndef SYSTEMCONFIG_H
#define SYSTEMCONFIG_H

#include "simpleini/SimpleIni.h"
#include <exception>
#include <string>
#include <vector>
#include <map>

#define SYSTEMCONFIG HIM::SystemConfig::getInstance()
#define CONFIGPATH "../data/config/default.ini"
#define PARAMETER "parameter"

namespace HIM {

class ConfigException : public std::exception{
private:
    std::string str;
public:
    ConfigException(std::string s){
        str=s;
    }
    const char * what () const throw () {
        return str.c_str();
    }
};

class SystemConfig
{
public:
    static SystemConfig& getInstance(){
        static SystemConfig systemConfig;
        return systemConfig;
    }

    CSimpleIniA& getIni(){return ini;};
    // 加载ini文件
    bool loadfile(const std::string &path);
    // 保存ini文件
    bool saveFile(const std::string &fileName);

    // 设置INI数据的存储格式，参数为true时保存为UTF-8格式，否则为本地编码格式
    void setUnicode(const bool utf8 = true);
    // 是否允许一个关键字对应多个值，默认为允许；若不允许，则将最后一个值作为此关键字关联的值，其他删除
    void setMultiKey(const bool multKey = false);
    // 获取ini文件字符串
    std::string getIniStr();

    // 添加一个新的section
    bool addSection(const std::string &section);
    // 添加一个新的key和value，value可以默认为空
    bool addValue(const std::string &section, const std::string &key, const std::string &value = "");
    bool addLongValue(const std::string &section, const std::string &key, const long value = 0);
    bool addDoubleValue(const std::string &section, const std::string &key, const double value = 0.0);
    bool addBoolValue(const std::string &section, const std::string &key, const bool value = false);

    // 修改value，如果key不存在，则会创建key和value
    bool setValue(const std::string &section, const std::string &key, const std::string &value);
    bool setLongValue(const std::string &section, const std::string &key, const long value = 0);
    bool setDoubleValue(const std::string &section, const std::string &key, const double value = 0.0);
    bool setBoolValue(const std::string &section, const std::string &key, const bool value = false);

    // 删除key
    bool deleteKey(const std::string &section, const std::string &key);
    // 删除key，如果最后一个key也被删除了，那么section也会被一起删除掉
    bool deleteKeys(const std::string &section, const std::string &key, const bool deleteSectionIfEmpty = true);
    // 删除section，整个section和其中的所有键值
    bool deleteSection(const std::string &section);

    // 获取string类型值
    std::string getValue(const std::string &section, const std::string &key, const std::string &defualtValue = "");
    // 获取char类型值
    char getValueC(const std::string &section, const std::string &key, const char &defualtValue = '\0');
    // 获取long、int、short类型
    long getLongValue(const std::string &section, const std::string &key, const short &defualtValue = -1);
    // 获取double、float类型
    double getDoubleValue(const std::string &section, const std::string &key, const double &defualtValue = 0.0);
    // 获取bool类型
    bool getBoolValue(const std::string &section, const std::string &key, const bool &defualtValue = false);
    // 获取section里有多少值
    int getSectionSize(const std::string &section);
    // 遍历所有
    void printAll();

private:
    std::string error_info(const std::string& cs,int errnum);

private:
    SystemConfig(){};
    ~SystemConfig(){};
    SystemConfig(const SystemConfig&) = delete ;
    SystemConfig& operator = (const SystemConfig&) = delete ;

private:
    CSimpleIniA ini;
};

}

#endif // SYSTEMCONFIG_H
